package com.xinhe.web.service;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.google.gson.Gson;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.xinhe.web.common.Result;
import com.xinhe.web.entity.Image;
import com.xinhe.web.entity.QImage;
import com.xinhe.web.redis.ObjectRedisTemplate;
import com.xinhe.web.reposity.ImageRepository;
import com.xinhe.web.request.ShortMessageExpireView;
import com.xinhe.web.util.Random;
import com.xinhe.web.util.Snowflake;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.inject.Provider;
import javax.persistence.EntityManager;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Service
public class AliyunService {
    @Value("${file.aliyun.endpoint}")
    private String endpoint;
    @Value("${file.aliyun.regionId}")
    private String regionId;

    @Value("${file.aliyun.accessKeyId}")
    private String accessKeyId;

    @Value("${file.aliyun.accessKeySecret}")
    private String accessKeySecret;

    @Value("${file.aliyun.bucketName}")
    private String bucketName;
    public static final String path = "xinhe";

    @Autowired
    ImageRepository imageRepository;
    //查询工厂
    private JPAQueryFactory queryFactory;
    @Autowired
    private Provider<EntityManager> entityManager;

    @PostConstruct
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }

    @Autowired
    private ObjectRedisTemplate<String, ShortMessageExpireView> redisTemplate;

    public Result uploadPhoto(MultipartFile file) {
        String fileTitle = file.getOriginalFilename();
        if (!file.isEmpty()) {
            OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            String fileName = fileTitle;
            InputStream input = null;
            try {
                input = file.getInputStream();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            String fileKey = path + "/" + fileName;
            client.putObject(bucketName, fileKey, input);
            String url = "https://xinhebucket.oss-cn-beijing.aliyuncs.com" + "/" + fileKey;
            return Result.ok(url);
        }
        return Result.failed(10003, "上传失败");
    }

    public void sendCodeByMobileV(String mobile, String timeZone) {
        String code = Random.nextNumber(1001, 9999) + "";
        log.info("------- 阿里云发送验证码, mobil: ${}, code: ${}", mobile, code);
        boolean rsFlag = false;
        //产品名称:云通信短信API产品,开发者无需替换
        final String product = "Dysmsapi";
        //产品域名,开发者无需替换
        final String domain = "dysmsapi.aliyuncs.com";
        try {
            //初始化acsClient,暂不支持region化
            IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            DefaultProfile.addEndpoint("cn-hangzhou", product, domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);

            //组装请求对象-具体描述见控制台-文档部分内容
            SendSmsRequest request = new SendSmsRequest();
            //必填:待发送手机号
            request.setPhoneNumbers(mobile);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName("芯禾玉品");
            //必填:短信模板-可在短信控制台中找到
            request.setTemplateCode("SMS_290191989");
            request.setTemplateParam("{\"code\": " + code + "}");
            //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
            //request.setSmsUpExtendCode("90997");
            //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
            //request.setOutId("yourOutId");
            //hint 此处可能会抛出异常，注意catch
            log.info("SendCode request:{}", new Gson().toJson(request));
            SendSmsResponse res = acsClient.getAcsResponse(request);
            log.info("SendCode:{}", new Gson().toJson(res));
            if ("OK".equals(res.getCode())) {
                rsFlag = true;
            } else {
                log.info("短信发送失败" + res.getCode() + ", " + res.getMessage());
            }
        } catch (Exception e) {
            log.error("短信发送失败", e);
        }
        //保存redis
        redisCache(mobile, code);
    }

    private void redisCache(String phoneNumber, String code) {
        HashOperations<String, String, ShortMessageExpireView> ops = this.redisTemplate.opsForHash();
        Map<String, ShortMessageExpireView> verifyCodes = ops.entries("alyun-sms");
        Integer expireSecond = 60;
        ShortMessageExpireView view = new ShortMessageExpireView();
        view.setCode(code);
        view.setPhone(phoneNumber);
        view.setExpireTime(Long.valueOf(System.currentTimeMillis() + (expireSecond.intValue() * 1000)));
        verifyCodes.put(phoneNumber, view);
        ops.putAll("alyun-sms", verifyCodes);
    }


    public Result saveImageText(MultipartFile file, String type, Integer sequence) {
        Result result = uploadPhoto(file);
        String url = (String) result.getData();
        Image image = new Image();
        image.setId(Snowflake.generateId());
        image.setType(type);
        image.setSequence(sequence);
        image.setUrl(url);
        imageRepository.save(image);
        return Result.ok();
    }

    public QueryResults<Image> pageImageText(String type, int pageNum, int pageSize) {
        QImage qImage = QImage.image;
        BooleanBuilder builder = new BooleanBuilder();
        if (!Objects.isNull(type)) {
            builder.and(qImage.type.contains(type));
        }
        return queryFactory.select(
                Projections.bean(
                        Image.class,
                        qImage.id,
                        qImage.type,
                        qImage.sequence,
                        qImage.url
                )
        ).from(qImage)
                .where(builder).offset(pageNum * pageSize).limit(pageSize).fetchResults();
    }

    public Result detailImageText(Long id) {
        Image image = imageRepository.findById(id).get();
        return Result.ok(image);
    }

    public Result deleteImageText(Long id) {
        imageRepository.deleteById(id);
        return Result.ok();
    }

    public Result validCode(String phone, String code) {
        HashOperations<String, String, ShortMessageExpireView> ops = this.redisTemplate.opsForHash();
        Map<String, ShortMessageExpireView> verifyCodes = ops.entries("alyun-sms");
        ShortMessageExpireView shortMessageExpireView = verifyCodes.get(phone);
        long nowTime = System.currentTimeMillis();
        if (shortMessageExpireView == null) {
            return Result.failed(101,"请重新获取短信验证码");
        }
        if (!code.equals(shortMessageExpireView.getCode())) {
            return Result.failed(102,"短信验证码错误");
        }
        if (nowTime >= shortMessageExpireView.getExpireTime().longValue()) {
            return Result.failed(103,"短信验证码已失效");
        }
        if (!code.equals(shortMessageExpireView.getCode())) {
            return Result.failed(102,"短信验证码错误");
        }
        ops.delete("alyun-sms", new Object[]{phone});
        return Result.ok();
    }

}